package com.leantech.android.browser

import android.os.Build
import androidx.lifecycle.ProcessLifecycleOwner
import androidx.lifecycle.lifecycleScope
import coil.ImageLoader
import coil.decode.GifDecoder
import coil.decode.VideoFrameDecoder
import coil.util.DebugLogger
import com.cscj.android.repository.datastore.AppDataStore
import com.lean.android.ad.core.config.AdParamsProvider
import com.lean.android.ad.core.config.AppInfoProvider
import com.lean.android.ad.core.config.ChannelInfoProvider
import com.lean.android.ad.core.config.RewardCustomFloatView
import com.lean.android.ad.core.splash.SplashAdView
import com.lean.android.channel.vasdolly.VasdollyChannelProvider
import com.leantech.android.browser.ad.AdParamsProviderImpl
import com.leantech.android.browser.ad.AppInfoProviderImpl
import com.leantech.android.browser.ad.RewardCustomFloatViewImpl
import com.leantech.android.browser.ad.SplashAdViewImpl
import com.leantech.android.browser.ui.InterstitialAdViewModel
import com.leantech.android.browser.ui.browser.viewmodel.BrowserTabViewModel
import com.leantech.android.browser.ui.browser.viewmodel.BrowserViewModel
import com.leantech.android.browser.ui.browser.viewmodel.FavoriteStateViewModel
import com.leantech.android.browser.ui.browser.viewmodel.ShortCutEntryViewModel
import com.leantech.android.browser.ui.favorites.vm.BrowserHistoryViewModel
import com.leantech.android.browser.ui.favorites.vm.FavoritesViewModel
import com.leantech.android.browser.ui.search.CustomSearchEngineViewModel
import com.leantech.android.browser.ui.search.SearchViewModel
import com.leantech.android.browser.ui.setting.BrowserSettingViewModel
import com.leantech.android.browser.ui.shortcut.viewmodel.ShortCutViewModel
import com.leantech.android.browser.utils.CrashHandler
import com.leantech.android.browser.utils.UrlProvider
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.runBlocking
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import org.koin.androidx.viewmodel.dsl.viewModel
import org.koin.core.qualifier.named
import org.koin.dsl.module

private val coroutineScopeModule = module {
    single<CoroutineScope> {
        named("app")
        ProcessLifecycleOwner.get().lifecycleScope
    }
}

private val interceptorModule = module {
    single {
        Interceptor { chain ->
            val request = chain.request().newBuilder()
            val appClient = getProperty("appClient", "")
            request.addHeader("appClient", appClient)
            request.addHeader("model", Build.MODEL)
            val deviceId = runBlocking {
                get<AppDataStore>().getDeviceId()
            }
            val channelInfoProvider = get<ChannelInfoProvider>()
            request.addHeader("deviceId", deviceId)
            request.addHeader("channel", channelInfoProvider.getChannel())
            request.addHeader("realChannel", channelInfoProvider.getRealChannel())
            request.addHeader("version", BuildConfig.VERSION_NAME)
            chain.proceed(request.build())
        }
    }
}

private val coilModule = module {
    single {
        val okhttpClient = get<OkHttpClient>()
        ImageLoader.Builder(get()).callFactory(okhttpClient).components {
            add(GifDecoder.Factory())
            add(VideoFrameDecoder.Factory())
        }.respectCacheHeaders(false).apply {
            if (BuildConfig.DEBUG) {
                logger(DebugLogger())
            }
        }.bitmapFactoryMaxParallelism(10).build()
    }
}

private val viewModelModule = module {
    viewModel { BrowserTabViewModel() }
    viewModel { SearchViewModel() }
    viewModel { CustomSearchEngineViewModel() }
    viewModel { BrowserViewModel() }
    viewModel { InterstitialAdViewModel() }
    viewModel { FavoritesViewModel() }
    viewModel { FavoriteStateViewModel() }
    viewModel { BrowserHistoryViewModel() }
    viewModel { ShortCutViewModel() }
    viewModel { ShortCutEntryViewModel() }
    viewModel { BrowserSettingViewModel() }
}

private val adModule = module {
    single<AppInfoProvider> { AppInfoProviderImpl(get()) }
    single<AdParamsProvider> { AdParamsProviderImpl() }
    single<SplashAdView> { SplashAdViewImpl() }
    single<RewardCustomFloatView> { RewardCustomFloatViewImpl() }
    single<ChannelInfoProvider> { VasdollyChannelProvider(get()) }
}

val appModule = module {
    single(createdAtStart = true) {
        AppInitial()
    }
    single {
        AdInitial()
    }
    single {
        CrashHandler()
    }

    single { HotSplashAdState() }

    single { UrlProvider() }

    includes(
        adModule, coroutineScopeModule, interceptorModule, coilModule, viewModelModule
    )
}